﻿namespace ChessToys
{
    using System;
    using System.Collections.Generic;

    /// <summary>
    /// <see cref="IMoveGenerator"/> for <see cref="Pawn"/>.
    /// </summary>
    public class PawnMoveGenerator : AbstractPieceMoveGenerator<Pawn>
    {
        /// <inheritdoc />
        protected override ISet<Move> GenerateForSpecificPiece(Board board, Position start, Pawn piece)
        {
            // prepare result
            ISet<Move> moves = new HashSet<Move>();
            // get increment
            Position increment = GetIncrement(piece);
            // from initial position a two field wide step is allowed
            if (IsInitialPosition(board, start, piece))
            {
                moves.UnionWith(Crawl(board, start, increment, new Position(-1, (start + increment + increment + increment).Y)));
            
            }
            // single step forward
            else
            {
                moves.UnionWith(Crawl(board, start, increment, new Position(-1, (start + increment + increment).Y)));
            }
            // pawn promotion
            PawnPromotion(moves, piece, board);
            // TODO strikes
            // return result
            return moves;
        }

        private void PawnPromotion(ISet<Move> moves, Pawn pawn, Board board)
        {
            foreach (Move move in new HashSet<Move>(moves))
            {
                if ((pawn.PlayDirection == Pawn.Direction.Up && move.End.Y == 0) || (pawn.PlayDirection == Pawn.Direction.Down && move.End.Y == board.Size - 1))
                {
                    // remove current move
                    moves.Remove(move);
                    // add queen promotion
                    moves.Add(new PawnPromotionMove(move.Start, move.End, new Queen(pawn.Color)));
                    // add bishop promotion
                    moves.Add(new PawnPromotionMove(move.Start, move.End, new Bishop(pawn.Color)));
                    // add knight promotion
                    moves.Add(new PawnPromotionMove(move.Start, move.End, new Knight(pawn.Color)));
                    // add rock promotion
                    moves.Add(new PawnPromotionMove(move.Start, move.End, new Rock(pawn.Color)));
                }
            }
        }

        private Position GetIncrement(Pawn pawn)
        {
            if (pawn.PlayDirection == Pawn.Direction.Down)
            {
                return new Position(0, 1);
            }
            else
            {
                return new Position(0, -1);
            }
        }

        private bool IsInitialPosition(Board board, Position position, Pawn pawn)
        {
            // play direction: down
            if (pawn.PlayDirection == Pawn.Direction.Down)
            {
                return position.Y == 1;
            }
            // playdirection: up
            else
            {
                return position.Y == board.Size - 2;
            }
        }
    }
}
